package com.aube.interact.taste.controller;

import android.content.Context;
import android.os.Handler;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.widget.RelativeLayout;

import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.aube.interact.taste.card.BaseCardNew;
import com.aube.interact.taste.card.ViewGenerator;
import com.aube.interact.taste.model.OptionItem;
import com.aube.interact.taste.model.OptionResultModel;
import com.aube.interact.taste.model.ReportResultModel;
import com.aube.interact.taste.model.TimeLineData;
import com.aube.interact.taste.model.TimeLineModel;
import com.aube.interact.taste.model.TimeLinePiece;
import com.huyn.baseframework.dynamicload.video.AbstractController;
import com.huyn.baseframework.dynamicload.video.model.GoodsItem;
import com.huyn.baseframework.model.ChannelDetail;
import com.huyn.baseframework.net.BFJSONRequest;
import com.huyn.baseframework.net.HttpRequestLoader;
import com.huyn.baseframework.net.OpenApi;
import com.huyn.baseframework.statistics.AubeStatisticEvents;
import com.huyn.baseframework.statistics.AubeStatisticTool;
import com.huyn.baseframework.statistics.EventValuePair;
import com.huyn.baseframework.utils.StringUtils;
import com.huyn.baseframework.utils.Utils;

import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by hill on 10/24.
 */
public class CardsController extends AbstractController<TimeLinePiece> {
    private final String TAG = "Aube/CardsController";

    private Handler mHandler;

    private TimeLineData data;

    public CardsController(Context context, ViewGroup mRoot) {
        super(context, mRoot);

        mHandler = new Handler(context.getMainLooper());
    }

    public CardsController(Context context, ViewGroup mRoot, ChannelDetail mChannel, IControllerCallback callback) {
        super(context, mRoot, mChannel, callback);

        mHandler = new Handler(context.getMainLooper());
    }

    public boolean setupCards(long selectedIndex, boolean freshData, boolean autoBegin) {
        if(setupCards(selectedIndex, autoBegin))
            return true;

        if(freshData) {
            loadTimeLine(selectedIndex);
            return true;
        }

        return false;
    }

    private boolean setupCards(long selectedIndex, boolean autoBegin) {
//        mCurrentData = null;
        clearCardsList();
        if(data == null || data.timeline == null)
            return false;
        synchronized (mCardsList) {
            mCardsList.clear();
            long currentSecond = selectedIndex / 1000;
            List<TimeLinePiece> temp = data.formatList();
            for(TimeLinePiece item : temp) {
                if(item.endSeconds <= currentSecond)
                    continue;
                if(TimeLinePiece.TYPE_VIDEO.equalsIgnoreCase(item.type))
                    continue;
                Utils.Log(TAG, "start at:" + currentSecond + "___" + item.type + "___" + item.startSeconds + "/" + item.endSeconds);
                mCardsList.add(item);
            }

            if(!autoBegin) {
//                locateCardByTime(selectedIndex);
                if(mCardsList.size() > 0 && mCurrentData != null) {
                    TimeLinePiece firstItem = mCardsList.get(0);
                    if(mCurrentData.rid.equalsIgnoreCase(firstItem.rid)) {
                        locateCardByTime(selectedIndex);
                        return true;
                    }
                }
                manageCard(null);
            }
        }
        return true;
    }

    private long mCurrent = 0;
    public boolean locateCardByTime(long current) {
        if(current < 0)
            return manageCard(null);

        synchronized (mCardsList) {
            long currentSecond = current / 1000;

            mCurrent = currentSecond;

            if(mCurrentData != null) {
                if(mCurrentData.endSeconds <= currentSecond || mCurrentData.startSeconds > currentSecond)
                    mCurrentData = null;
                else
                    return manageCard(mCurrentData);
            }

            if(mCardsList.size() == 0)
                return manageCard(null);

            TimeLinePiece firstItem = mCardsList.get(0);
            if(firstItem.startSeconds <= currentSecond && firstItem.endSeconds > currentSecond) {
//                Utils.Log(TAG, "CARDS____load card:" + firstItem.title + "_type:" + firstItem.type + " at time:" + currentSecond);
                if(manageCard(firstItem))
                    mCardsList.remove(0);
            } else if(firstItem.endSeconds <= currentSecond) {
//                Utils.Log(TAG, "CARDS____remove:" + firstItem.title + "_endSeconds:" + firstItem.endSeconds + " at time:" + currentSecond);
                mCardsList.remove(0);
            } else {
//                Utils.Log(TAG, "CARDS____state:" + firstItem.title + "_startseconds:" + firstItem.startSeconds + "_endSeconds:" + firstItem.endSeconds);
            }

            return manageCard(null);
        }
    }

    public boolean manageCard(TimeLinePiece data) {
        if(mAnimating.get())
            return false;
        if(data != null) {
            if(TimeLinePiece.TYPE_QA.equalsIgnoreCase(data.type)) {
                int revealTime = data.detail.revealTheAnswer;

                //更新倒计时
                updateCountDown(revealTime > mCurrent ? (revealTime - mCurrent + "s") : "");
            }
            if(mCurrentData != null)  {
                if(mCurrentData.rid.equalsIgnoreCase(data.rid) && hasCard())
                    return true;
                else {
                    appendToScreen(data);
                    mCurrentData = data;
                }
            } else {
                appendToScreen(data);
                mCurrentData = data;
            }
        } else {
            mCurrentData = null;
            if(hasCard()) {
                removeFromScreen();
            }
        }
        return true;
    }

    private void updateCountDown(String time) {
        if(hasCard())
            ((BaseCardNew) mCardRoot.getChildAt(0)).updateCountDown(time);
    }

    public void appendToScreen(TimeLinePiece data) {
        Utils.Log(Utils.LogType.DEBUG, TAG, "appendToScreen start");
        removeFromScreen();
        if(mAnimating.get())
            return;
        final BaseCardNew view = ViewGenerator.getView(data, mChannel, context);
        if (view != null) {
            // get iDataSyncHelper ready first
            setIDataSyncHelper(view);
            //统计卡片出现事件
            AubeStatisticTool.getInstance(context).report(AubeStatisticEvents.INTERACT_DISPLAY,
                    AubeStatisticEvents.formatValues(new EventValuePair("vid", mChannel.videoid), new EventValuePair("rid", data.getRid()), new EventValuePair("type", data.type)));

            mAnimating.set(true);

            view.setupSender(new BaseCardNew.IDataSyncSender() {
                @Override
                public void startSync(String id, boolean oneTime) {
                    //发送请求
                    Utils.Log(Utils.LogType.DEBUG, TAG, "startSync");
                    doRequest(id, oneTime);
                }

                @Override
                public void postResult(String id, List<OptionItem> result, String cancelId, String selectedId) {
                    checkResult(id, new OptionResultModel(result), cancelId, selectedId, true);
                }

                @Override
                public void close() {
                    mCurrentData = null;
                    removeFromScreen();
                }

                @Override
                public void onAddRewardGoods(List<GoodsItem> data) {
                    if(iControllerCallback != null)
                        iControllerCallback.onGoodsAdd(data);
                }
            });

            view.animIn((RelativeLayout) mCardRoot, new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {

                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    mAnimating.set(false);
                    view.onCardInAnimEndEvent();
                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });
        }

        Utils.Log(Utils.LogType.DEBUG, TAG, "appendToScreen end");
    }

    private boolean hasCard() {
        return mCardRoot.getChildCount() > 0;
    }

    private AtomicBoolean mAnimating = new AtomicBoolean(false);
    @Override
    public void removeFromScreen() {
//        super.removeFromScreen();
        if(!mAnimating.get() && hasCard()) {
            mAnimating.set(true);
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    final View view = mCardRoot.getChildAt(0);
                    if(view instanceof BaseCardNew) {
                        ((BaseCardNew) view).animOut(new Animation.AnimationListener() {
                            @Override
                            public void onAnimationStart(Animation animation) {

                            }

                            @Override
                            public void onAnimationEnd(Animation animation) {
                                Utils.Log(TAG, "[removeFromScreen] animOut done");
                                mCardRoot.removeView(view);
                                mAnimating.set(false);
                            }

                            @Override
                            public void onAnimationRepeat(Animation animation) {

                            }
                        });
                    } else {
                        mCardRoot.removeView(view);
                        mAnimating.set(false);
                    }
                }
            });
//            mCardRoot.removeAllViews();
        }
        removeIDataSyncHelper();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        iDataSyncHelper = null;
        mHandler.removeCallbacksAndMessages(null);
        if(data != null)
            DataManager.getInstance(context).save(data.videoid);
    }

    private IDataSyncHelper iDataSyncHelper;

    private void setIDataSyncHelper(IDataSyncHelper helper) {
        this.iDataSyncHelper = helper;
    }

    private void removeIDataSyncHelper() {
        if(iDataSyncHelper != null)
            iDataSyncHelper.removeSender();
        iDataSyncHelper = null;
    }

    public interface IDataSyncHelper {
        public void syncData(OptionResultModel response);
        public void syncPreviewData(ReportResultModel result);
        public boolean IsPreviewDataSynced();
        public void removeSender();
    }

    /**
     * 从服务器上 获取 data count
     * @param id  卡片id(rid)
     * @param oneTime   是否需要loop request
     */
    protected void doRequest(final String id, final boolean oneTime) {
        HashMap<String, String> parameterMap = new HashMap<>();
        parameterMap.put("rid", id);
        final String optionId = DataManager.getInstance(context).getSelectedOptionId(id);
        if(StringUtils.isNotBlank(optionId))
            parameterMap.put("optionId", optionId);
        parameterMap.put(OpenApi.API_METHOD, OpenApi.DATA_COUNT);
        BFJSONRequest rq = new BFJSONRequest(ReportResultModel.class, parameterMap, new Response.Listener<ReportResultModel>() {

            @Override
            public void onResponse(ReportResultModel response) {
                //DataStateController.updateOptionCount(response);

                if(iDataSyncHelper != null && !iDataSyncHelper.IsPreviewDataSynced())
                    iDataSyncHelper.syncPreviewData(response);

                if(response != null)
                    checkResult(id, new OptionResultModel(response.getOptions()), null, optionId, oneTime);
            }

            @Override
            public void onErrorResponse(VolleyError error) {
            }

            @Override
            public void onStart() {
            }
        });
        HttpRequestLoader.getInstance(context).startCacheLoader("", rq, true);
    }

    /**
     * 处理服务器返回的data count数据
     * @param id
     * @param response
     * @param cancelId
     * @param selectedId
     * @param oneTime
     */
    private void checkResult(final String id, OptionResultModel response, String cancelId, String selectedId, final boolean oneTime) {
        if(response == null || !response.success() || response.data == null|| mCurrentData == null)
            return;

        if(!id.equalsIgnoreCase(mCurrentData.rid))
            return;

        if(iDataSyncHelper == null)
            return;

        if(iControllerCallback.isPlaying()) {
            int totalCount = 0;
            int maxCount = 0;
            String maxOptionId = "";
            String currentOptionId = DataManager.getInstance(context).getSelectedOptionId(id);
            if(StringUtils.isNotBlank(currentOptionId)) {
                for(OptionItem item : response.data) {
                    DataManager.getInstance(context).updateOptionCount(item.optionId, item.count);
                    if(maxCount < item.count) {
                        maxCount = item.count;
                        maxOptionId = item.optionId;
                    }
                    totalCount += item.count;
                }
                DataManager.getInstance(context).updateMaxCountOptionId(id, maxOptionId);
                DataManager.getInstance(context).updateTotalCount(id, totalCount);

                if(currentOptionId.equalsIgnoreCase(selectedId)) {
                    int count = response.getAnswerCount(selectedId);
                    DataManager.getInstance(context).updateOptionCount(selectedId, count > 0 ? count : 1);
                } else {
                    DataManager.getInstance(context).updateOptionCount(currentOptionId, response.getAnswerCount(currentOptionId), false);
                    if(StringUtils.isNotBlank(selectedId)) {
                        DataManager.getInstance(context).updateOptionCount(selectedId, response.getAnswerCount(selectedId), true);
                    } else {
                    }
                }
            } else {
                for(OptionItem item : response.data) {
                    if(maxCount < item.count) {
                        maxCount = item.count;
                        maxOptionId = item.optionId;
                    }
                    totalCount += item.count;

                    if(item.optionId.equalsIgnoreCase(selectedId))
                        DataManager.getInstance(context).updateOptionCount(selectedId, item.count, true);
                    else
                        DataManager.getInstance(context).updateOptionCount(item.optionId, item.count);
                }
                DataManager.getInstance(context).updateMaxCountOptionId(id, maxOptionId);
                DataManager.getInstance(context).updateTotalCount(id, totalCount);
            }

            iDataSyncHelper.syncData(response);
        }

        if(oneTime)
            return;

        sendNextMessage(id, oneTime);
    }

    private void sendNextMessage(final String id, final boolean oneTime) {
        mHandler.removeCallbacksAndMessages(null);
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if(iControllerCallback != null && iControllerCallback.isPlaying())
                    doRequest(id, oneTime);
                else if(!oneTime)
                    sendNextMessage(id, oneTime);
            }
        }, 1000);
    }

    public void loadTimeLine(final long selectedIndex) {
        if(mChannel == null) {
            Utils.showToast(context, "没有节目");
            return;
        }

        String showId = mChannel.showid;
        String videoId = mChannel.videoid;

        HashMap<String, String> parameterMap = new HashMap<String, String>();
        parameterMap.put(OpenApi.API_METHOD, OpenApi.TIMELINE_WITHOUT_VIDEO);
        parameterMap.put("showid", showId);
        parameterMap.put("videoid", videoId);
        BFJSONRequest request = new BFJSONRequest(TimeLineModel.class, parameterMap, new Response.Listener<TimeLineModel>() {

            @Override
            public void onResponse(TimeLineModel response) {
                TimeLineData mData = response.data;

                if(response.success()) {
                    if(mData == null)
                        return;

                    data = mData;

                    String bgUrl = data.getBgUrl();
                    if(StringUtils.isNotBlank(bgUrl) && iControllerCallback != null)
                        iControllerCallback.setBg(bgUrl);

                    DataManager.getInstance(context).restore(data.videoid);

                    setupCards(selectedIndex, true);
                } else {
//                    Utils.showToast(context, response.errormsg);
                }
            }

            @Override
            public void onErrorResponse(VolleyError error) {
            }

            @Override
            public void onStart() {
            }
        });
        request.setTag(TAG);
        HttpRequestLoader.getInstance(context).startCacheLoader("", request, true);
    }

}
